package com.ck.client.controller;

import com.ck.client.service.ClientService;
import com.ck.common.model.OperationResult;
import com.ck.common.model.bo.DeviceReportBO;
import com.ck.core.annotation.ClientPermissionRequired;
import com.ck.core.constant.BusinessConstant;
import com.ck.core.lock.LockConstant;
import com.ck.core.lock.RedisDistributeLock;
import com.ck.core.lock.RedisLock;
import com.ck.core.util.HttpUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**
 * <p>Title: CkClientController</p>
 * <p>Description: 创客客户端主动发起请求与服务端进行数据交互</p>
 *
 * @author huangf
 * @date 2018年7月17日
 */
@Controller
@ClientPermissionRequired
public class CkClientController {
    private static Logger logger = LoggerFactory.getLogger(CkClientController.class);
    @Autowired
    private ClientService clientService;
    @Autowired
    private RedisDistributeLock distributeLock;
    /**
     * 默认分辨率
     */
    private static String DEFAULT_RESOLUTION = "1080x1920";

    /**
     * 终端实时上报信息
     *
     * @return
     */
    @ResponseBody
    @PostMapping(value = "/report")
    public OperationResult<Object> report(HttpServletRequest request, @RequestHeader("appversion") String softwareVersion,
                                          @RequestHeader("appversioncode") Integer softwareVersionCode,@RequestHeader("firmwareversion") String firmwareVersion, String intranetIP,@RequestHeader("networkingWay") String networkingWay) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            DeviceReportBO deviceReport = new DeviceReportBO(deviceCode, intranetIP, HttpUtils.getRemortIP(request), BusinessConstant.DEVICE_INFO_STATUS_ON_LINE, System.currentTimeMillis(), softwareVersion,softwareVersionCode, firmwareVersion,networkingWay);
            OperationResult<Object> result = clientService.deviceReport(deviceReport);
            return result;
        } catch (Exception e) {
            logger.error("ClientController report 终端上报信息接异常：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 终端首次注册或解绑后二次绑定
     *
     * @param softwareVersion
     * @param deviceMac
     * @param firmwareVersion
     * @param intranetIP
     * @param modelName
     * @return
     */
    @ResponseBody
    @PostMapping(value = "/register")
    public OperationResult<Object> register(HttpServletRequest request, @RequestHeader("appversion") String softwareVersion, @RequestHeader("mac") String deviceMac,
                                            @RequestHeader("resolution") String resolution,@RequestHeader("firmwareversion") String firmwareVersion,
                                            @RequestHeader("devicemodel") String modelName,String intranetIP) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            OperationResult<Object> result = clientService.deviceRegister(deviceCode, deviceMac, intranetIP, HttpUtils.getRemortIP(request), modelName, softwareVersion, firmwareVersion, resolution);
            return result;
        } catch (Exception e) {
            logger.error("ClientController register 终端注册异常：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 终端获取最新的设置信息包括：【开关机、开关屏、音量设置、重启、远程关机、WiFi探针开关、人脸识别开关】
     *
     * @return
     */
    @ResponseBody
    @PostMapping(value = "getNewestSetting")
    public OperationResult<Object> getNewestSetting(HttpServletRequest request) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            OperationResult<Object> result = clientService.getNewestSetting(deviceCode);
            return result;
        } catch (Exception e) {
            logger.error("ClientController getNewestSetting 获取最新设置信息失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 终端确认设置信息收到包括：【开关机、开关屏、音量设置、重启、远程关机、WiFi探针开关、人脸识别开关】更新缓存状态。更新数据库一次性设置。
     *
     * @return
     */
    @ResponseBody
    @PostMapping(value = "getNewestSettingReply")
    public OperationResult<Object> getNewestSettingReply(HttpServletRequest request, Long serialNo) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            OperationResult<Object> result = clientService.getNewestSettingReply(serialNo, deviceCode);
            return result;
        } catch (Exception e) {
            logger.error("ClientController getNewestSettingReply 获取最新设置信息反馈失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 获取升级数据
     */
    @ResponseBody
    @PostMapping(value = "getUpgrade")
    public OperationResult<Object> getUpgrade(HttpServletRequest request, @RequestHeader("appversion") String softwareVersionName,
                                              @RequestHeader("appversioncode") Integer softwareVersionCode, @RequestHeader("firmwareversion") String firmwareVer) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            OperationResult<Object> result = clientService.getUpgrade(deviceCode, softwareVersionName, softwareVersionCode, firmwareVer);
            return result;
        } catch (Exception e) {
            logger.error("ClientController getUpgrade 获取最新升级数据失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 升级成功后确认反馈
     */
    @ResponseBody
    @PostMapping(value = "getUpgradeReply")
    public OperationResult<Object> getUpgradeReply(HttpServletRequest request, @RequestHeader("appversion") String softwareVersionName,
                                                   @RequestHeader("appversioncode") Integer softwareVersionCode, @RequestHeader("firmwareversion") String firmwareVersion, Long serialNo) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            OperationResult<Object> result = clientService.getUpgradeReply(serialNo, deviceCode, softwareVersionName, softwareVersionCode, firmwareVersion);
            return result;
        } catch (Exception e) {
            logger.error("ClientController getUpgradeReply 获取最新升级数据反馈失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 获取最新广告数据（最新播放列表）
     *
     * @param residualCapacity 终端剩余容量(单位：字节)
     * @return
     */
    @ResponseBody
    @PostMapping(value = "getNewestProgram")
    public OperationResult<Object> getNewestProgram(HttpServletRequest request, @RequestParam("residualCapacity") Long residualCapacity) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            return clientService.getNewestProgram(deviceCode, residualCapacity);
        } catch (Exception e) {
            logger.error("ClientController getNewestProgram 获取最新节目信息失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }


    /**
     * 获取最新广告数据反馈
     */
    @ResponseBody
    @PostMapping(value = "getNewestProgramReply")
    public OperationResult<Object> getNewestProgramReply(HttpServletRequest request, Long serialNo) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            return clientService.getNewestProgramReply(serialNo, deviceCode);
        } catch (Exception e) {
            logger.error("ClientController getNewestProgramReply 获取最新节目信息反馈异常：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 上报节目数据的下载状态
     *
     * @param downloadProgramVersion 节目版本号
     * @param state                  0:已下载	; 1:下载中; 2:下载失败
     * @param failureReason          失败原因
     */
    @ResponseBody
    @PostMapping(value = "uploadProgramDownloadStatus")
    public OperationResult<Object> uploadProgramDownloadStatus(HttpServletRequest request,String downloadProgramVersion, Integer state, String failureReason) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            if (StringUtils.isBlank(downloadProgramVersion)) {
                return OperationResult.newValidateFailOperationResult("downloadProgramVersion不能为空");
            }
            if (state == null) {
                return OperationResult.newValidateFailOperationResult("state不能为空");
            }
            OperationResult<Object> result;
            try (RedisLock lock = distributeLock.getLock((LockConstant.UPLOAD_PROGRAM_DOWNLOAD_STATUS_LOCK_PREFIX + downloadProgramVersion),
                    LockConstant.DEFAULT_TIMEOUT_MILLS, LockConstant.MAX_RETRY_TIMES, LockConstant.RETRY_INTERVAL_TIME_MILLIS)) {
                if (null != lock) {
                    result = clientService.uploadProgramDownloadStatus(deviceCode, downloadProgramVersion, state, failureReason);
                } else {
                    result = OperationResult.newValidateFailOperationResult("网络繁忙，请稍候再试");
                }
            }
            return result;
        } catch (Exception e) {
            logger.error("ClientController uploadProgramDownloadStatus 上报广告的下载状态失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 上传终端日志
     */
    @ResponseBody
    @PostMapping(value = "uploadLog")
    public OperationResult<Object> uploadLog(HttpServletRequest request, String url, String type) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            OperationResult<Object> result = clientService.uploadLog(deviceCode, url, type);
            return result;
        } catch (Exception e) {
            logger.error("ClientController uploadLog 上传终端日志失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

    /**
     * 外部操作设置，同步到服务端（如：运维人员现场调低音量。需要将该音量值上传到服务器入库）
     *
     * @param volume     音量
     * @return
     */
    @ResponseBody
    @PostMapping(value = "settingSync")
    public OperationResult<Object> settingSync(HttpServletRequest request, Integer volume) {
        String deviceCode = (String) request.getAttribute(BusinessConstant.CHAR_DEVICE_CODE);
        try {
            OperationResult<Object> result = clientService.settingSync(volume, deviceCode);
            return result;
        } catch (Exception e) {
            logger.error("ClientController settingSync 操作设置同步到服务器失败：【" + deviceCode + "】" + e.getMessage(), e);
            return OperationResult.newSystemErrorOperationResult();
        }
    }

}
